package logger

import (
	"context"
	"os"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

// Logger 是生产环境 Zap Logger 封装
type Logger struct {
	ZapLogger *zap.Logger
	level     zap.AtomicLevel
}

// NewLogger 初始化生产环境日志
func NewLogger(filename string, maxSize, maxBackups, maxAge int, compress bool, level zapcore.Level) (*Logger, error) {
	// lumberjack 做日志切割
	lumberJackLogger := &lumberjack.Logger{
		Filename:   filename,
		MaxSize:    maxSize,    // MB
		MaxBackups: maxBackups, // 保留备份文件数
		MaxAge:     maxAge,     // 天数，自动删除旧日志
		Compress:   compress,   // 是否压缩
	}

	// zap 日志编码配置（生产推荐 JSON 格式）
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "ts",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,              // 小写级别
		EncodeTime:     zapcore.TimeEncoderOfLayout(time.DateTime), // ISO8601 格式时间
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder, // 文件短路径 + 行号
	}

	encoder := zapcore.NewJSONEncoder(encoderConfig)

	// 日志级别动态可变
	atomicLevel := zap.NewAtomicLevelAt(level)

	// 输出到文件和控制台（建议生产环境只输出文件，控制台可关闭）
	fileWriter := zapcore.AddSync(lumberJackLogger)
	consoleWriter := zapcore.AddSync(os.Stdout)

	core := zapcore.NewTee(
		zapcore.NewCore(encoder, fileWriter, atomicLevel),
		zapcore.NewCore(encoder, consoleWriter, atomicLevel),
	)

	// 构建Logger，启用调用栈，开发时可根据需要调整
	logger := zap.New(core,
		zap.AddCaller(),
		zap.AddCallerSkip(1),
		zap.AddStacktrace(zapcore.ErrorLevel), // 级别>=Error才记录堆栈
	)

	return &Logger{
		ZapLogger: logger,
		level:     atomicLevel,
	}, nil
}

// SetLevel 动态设置日志级别
func (l *Logger) SetLevel(level zapcore.Level) {
	l.level.SetLevel(level)
}

// Sync 确保缓冲日志写入磁盘
func (l *Logger) Sync() error {
	return l.ZapLogger.Sync()
}

// Debug 记录Debug日志
func (l *Logger) Debug(_ context.Context, msg string, fields ...zap.Field) {
	l.ZapLogger.Debug(msg, fields...)
}

// Info 记录Info日志
func (l *Logger) Info(_ context.Context, msg string, fields ...zap.Field) {
	l.ZapLogger.Info(msg, fields...)
}

// Warn 记录Warn日志
func (l *Logger) Warn(_ context.Context, msg string, fields ...zap.Field) {
	l.ZapLogger.Warn(msg, fields...)
}

// Error 记录Error日志
func (l *Logger) Error(_ context.Context, msg string, fields ...zap.Field) {
	l.ZapLogger.Error(msg, fields...)
}

// Fatal 记录Fatal日志，随后程序退出
func (l *Logger) Fatal(_ context.Context, msg string, fields ...zap.Field) {
	l.ZapLogger.Fatal(msg, fields...)
}
